# -*- mode: python ; coding: utf-8 -*-
import pygame
import numpy as np
import sys
import time

from src.config import config as cfg
from src.module import *


def show_text(screen, pos, text, color, font_bold=False, font_size=60, font_italic=False):
    # 获取系统字体，并设置文字大小
    cur_font = pygame.font.SysFont("宋体", font_size)
    # 设置是否加粗属性
    cur_font.set_bold(font_bold)
    # 设置是否斜体属性
    cur_font.set_italic(font_italic)
    # 设置文字内容
    text_fmt = cur_font.render(text, 1, color)
    # 绘制文字
    screen.blit(text_fmt, pos)


def main():
    # 初始化pygame
    pygame.init()
    screen_size = (cfg.SCREEN_X, cfg.SCREEN_Y)
    screen = pygame.display.set_mode(screen_size)
    pygame.display.set_caption('virus-fighter')
    clock = pygame.time.Clock()

    # 记载默认帧率
    frame = 0
    home_frame = 0
    speed_frame = 0
    punish_frame = 0
    start_time = 0
    punish_flash_count = 0
    score_size = 50
    is_show_snake = True
    is_punish = False

    # 加载模组
    ball = Ball.Ball()
    brick = Brick.Brick()
    food = Food.Food()
    snake = Snake.Snake()
    game_info = GameInfo.GameInfo()

    # 加载bgm
    bgm = r'./music/bgm.mp3'
    home_bgm = r'./music/home_bgm.mp3'
    pygame.mixer.init()
    print("播放bgm")
    track = pygame.mixer.music.load(home_bgm)
    pygame.mixer.music.play(loops=-1)

    # 加载图片
    help_img = pygame.image.load(cfg.HELP_IMG)
    bg_img = pygame.image.load(cfg.BG_IMG)
    win_img = pygame.image.load(cfg.WIN_IMG)
    thanks_img = pygame.image.load(cfg.THANKS_IMG)
    go_img = pygame.image.load(cfg.GO_IMG)
    back_img = pygame.image.load(cfg.BACK_IMG)
    virus_img = []
    for i in range(10):
        v_img = pygame.image.load('./img/v%d.png' % (i + 1))  # 加载病毒图片
        virus_img.append(v_img)
    medical_img = []
    for i in range(12):
        m_img = pygame.image.load('./img/m%d.png' % (i + 1))  # 加载医护图片
        medical_img.append(m_img)
    num_img = []
    for i in range(10):
        n_img = pygame.image.load('./img/%d.png' % i)  # 加载数字图片
        n_img = pygame.transform.smoothscale(n_img, (score_size, score_size))
        num_img.append(n_img)
    homes_img = []
    for i in range(4):
        h_img = pygame.image.load('./img/home%d.png' % (i + 1))  # 加载数字图片
        homes_img.append(h_img)
    drag_img = []
    for i in range(5):
        d_img = pygame.image.load('./img/drag%d.png' % (i + 1))  # 加载数字图片
        drag_img.append(d_img)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            if event.type == pygame.KEYDOWN:
                snake.change_direction(event.key)
                if event.key == pygame.K_SPACE and game_info.is_dead:
                    return main()
            elif (game_info.is_this_state(game_info.HOME)) and event.type == pygame.MOUSEBUTTONDOWN:
                # 在游戏欢迎界面时，根据鼠标位置判断是否开始游戏
                x, y = pygame.mouse.get_pos()
                print(x, y)
                if 165 <= x <= 435 and 470 <= y <= 550:
                    game_info.reset()
                    game_info.state = game_info.LOADING
            elif (game_info.is_this_state(game_info.THANKS)) and event.type == pygame.MOUSEBUTTONDOWN:
                # 在游戏致敬页面，可以选择回到首页
                x, y = pygame.mouse.get_pos()
                print(x, y)
                if 210 <= x <= 390 and 480 <= y <= 550:
                    game_info.state = game_info.HOME
                    pygame.mixer.music.stop()
                    track = pygame.mixer.music.load(home_bgm)
                    pygame.mixer.music.play(loops=-1)

        if game_info.is_this_state(game_info.HOME):
            # 没开始，就显示home页
            home_frame += 1
            index = home_frame % 4
            screen.blit(homes_img[index], (0, 0))
            screen.blit(go_img, (165, 470))
        if game_info.is_this_state(game_info.LOADING):
            # 没有加载关，就加载
            if not brick.has_stage(game_info.stage):
                # 没有了，通关了
                frame = 0
                game_info.state = game_info.WIN
                # pygame.mixer.music.stop()
                continue

            # 记录帧（stage loading 页面）
            frame += 1
            if frame < cfg.FPS * 2:
                screen.fill((27, 198, 111))
                show_text(screen, (200, 200), 'STAGE ' + str(game_info.stage), (255, 255, 255))
                pygame.display.update()
                continue
            else:
                brick.load_stage(game_info.stage)
                ball.reset()
                snake.reset()
                is_punish = False
                is_show_snake = True
                punish_flash_count = 0
                start_time = time.time()
                game_info.state = game_info.PLAYING
                pygame.mixer.music.stop()
                track = pygame.mixer.music.load(bgm)
                pygame.mixer.music.play(loops=-1)

        if game_info.is_this_state(game_info.PLAYING):
            speed_frame += 1
            # 将图片画到窗口上
            screen.blit(bg_img, (0, 0))
            # 画砖块
            for i, raw in enumerate(brick.bricks):
                for j, v in enumerate(raw):
                    # 大于0是病毒
                    if v > 0:
                        virus_img_trans = pygame.transform.smoothscale(virus_img[v - 1], (cfg.UNIT, cfg.UNIT))
                        screen.blit(virus_img_trans, (j * cfg.UNIT, i * cfg.UNIT))  # 将图片画到窗口上

            if speed_frame % snake.fps == 0:
                # 如果被惩罚中，需要重置，需要记punish_frame，如记录是否显示蛇（闪烁）
                if is_punish:
                    snake.punish_reset()
                    punish_frame += 1
                    if punish_frame % (cfg.FPS // 3) == 0:
                        is_show_snake = not is_show_snake
                        punish_flash_count += 1

                    if punish_flash_count >= cfg.PUNISH_FLASH_COUNT:
                        is_punish = False
                        is_show_snake = True
                        punish_flash_count = 0
                else:
                    # 如果不是惩罚时间，正常移动，正常判断是否撞病毒
                    snake.move()
                    is_punish = snake.is_crash_brick(brick.bricks)

            if is_show_snake:
                # 画蛇身 / 每一步+1分
                x = 0
                for index, node in enumerate(snake.body):
                    img_id = snake.get_img_queue()[index]
                    i, j, = node
                    x += 1
                    medical_img_trans = pygame.transform.smoothscale(medical_img[img_id],
                                                                     (cfg.UNIT - x // 4, cfg.UNIT - x // 4))
                    screen.blit(medical_img_trans, (i * cfg.UNIT, j * cfg.UNIT))  # 将图片画到窗口上

            # 食物处理 / 吃到+50分
            # # 当食物rect与蛇头重合,吃掉 -> Snake增加一个Node
            if food.pos == snake.body[0]:
                game_info.add_score(20)
                food.remove()
                snake.add_node()

            # 食物投递
            if not snake.is_enough():
                food.set(brick.bricks)
                i, j = food.pos
                help_img_trans = pygame.transform.smoothscale(help_img, (cfg.UNIT, cfg.UNIT))
                screen.blit(help_img_trans, (i * cfg.UNIT, j * cfg.UNIT))  # 将图片画到窗口上

            # 文字
            # 显示分数文字
            # 计算时间奖励默认1秒是值10分，满时间奖励是3000分，也就是有300s时间（）
            diff = int(time.time() - start_time)
            time_bonus = 3000 - diff * 10
            if time_bonus < 0:
                time_bonus = 0
            show_text(screen, (60, 10), 'stage ' + str(game_info.stage), (223, 223, 223), font_size=25)
            show_text(screen, (260, 10), 'scores: ' + str(game_info.score), (223, 223, 223), font_size=25)
            show_text(screen, (400, 10), 'time bonus: ' + str(time_bonus), (223, 223, 223), font_size=25)

            # 是否过关
            if np.sum(brick.bricks) == 0:
                game_info.add_stage()
                game_info.add_score(time_bonus)
                frame = 0
                game_info.state = game_info.LOADING

            # 球
            skip = False
            if speed_frame % ball.fps == 0:
                # 球体碰撞检测
                need_crash_check = True
                count = 0

                # 检测是否无路可走，是则跳过，先赋false
                # 记录当前方向，如果碰撞检测后，遇见相同的说明循环了，那就跳过移动方法
                direction = ball.direction
                while count < 4 and need_crash_check:
                    count += 1
                    need_crash_check = ball.check_crash(snake, brick, game_info)
                    if need_crash_check and direction[0] == ball.direction[0] and direction[1] == ball.direction[1]:
                        skip = True
                        break
                # 生死检测
                if not game_info.is_dead:
                    pass
                    if not skip:
                        ball.move()
            # 画球
            ball_img_trans = pygame.transform.smoothscale(drag_img[speed_frame % 5], (cfg.UNIT, cfg.UNIT))
            screen.blit(ball_img_trans, (ball.i * cfg.UNIT, ball.j * cfg.UNIT))  # 将图片画到窗口上

        if game_info.is_this_state(game_info.WIN):
            frame += 1
            if frame < cfg.FPS * 3:
                screen.blit(win_img, (0, 0))
                score = game_info.score
                num_pos_x, num_pos_y = 400, 349
                while score:
                    sub_score = score % 10
                    score = score // 10
                    screen.blit(num_img[sub_score], (num_pos_x, num_pos_y))  # 将图片画到窗口上
                    num_pos_x -= score_size * 2 // 3
                pygame.display.update()
            else:
                game_info.state = game_info.THANKS

        if game_info.is_this_state(game_info.THANKS):
            # 致敬页面
            screen.blit(thanks_img, (0, 0))
            # 返回按钮
            screen.blit(back_img, (210, 480))
            pygame.display.update()

        pygame.display.update()
        clock.tick(cfg.FPS)


if __name__ == '__main__':
    main()
